#include <string.h>
#include <stdio.h>
#include "data.h"
#include "inirw.h"
#include "platform.h"
#include "fsapi.h"
#include "log.h"

#define CONFIG_FILE "adminpara.ini"
#define FLASH_RUNTIMEINFOFILE "runtime.txt" //运行参数，经常变动
#define UPGRADE_CONFIG_FILE "httpconf"
#define CONFIG_FILE_DEFAULT_PART "DEV"

#define FLASH_RECORD_EVENT_MAX 2000  //告警和事件每个文件最大存储记录，两个文件循环存储，

#define FLASH_RECORD_EVENT "event1.txt"  //告警，事件记录文件
#define FLASH_RECORD_EVENT2 "event2.txt"  //告警，事件记录文件

#define FLASH_RECORD_TRACE_MAX 2000 //每个trace文件大小
#define FLASH_RECORD_TRACE "trace1.txt"
#define FLASH_RECORD_TRACE2 "trace2.txt"


struct config_defult{
	char_t *section;
	char_t *key;
	char_t *value;
};


static const struct config_defult cfg_def[]={

  {"DEV","teleph", "075586265503"},
  {"DEV","web", "www.ewellcharge.com"},
  {"DEV","company", "putn"},

  {"DEV","gw","192.168.1.1"},
  {"DEV","lip","192.168.1.231"},
  {"DEV","mask","255.255.255.0"},

  {"DEV","cp12v","3357"}, //cp 12v对应的采样值，需要校准
  {"DEV","cp9v","2420"},
  {"DEV","cp6v","1600"},
  {"DEV","softver","0"}, 
  {"DEV","pwm", "531"},  //pm占空比，可微调
  {"DEV","chargetest", "0"},    //0 运营模式 1 测试模式
  {"DEV","devmode", "1"}, // 1 交流桩 2 直流桩
  {"DEV","emmode","1"}, //0 电表 1 电表模块 
  {"DEV","embaud","2400"}, //电表波特率   
  {"DEV","authmode","on"}, //on ,off
  {"DEV","netmode","line"}, // line, wlan, gprs, gm510, CDMA, auto
  {"DEV","backlight","80"},
  {"DEV","advon", "180000"},  //广告灯箱打开时间
  {"DEV","advoff", "060000"}, //广告灯箱关闭时间
  {"DEV","servmode", "test"}, //后台模式 test  release,
  {"DEV","emidl","171209000056"}, //左枪电表
  {"DEV","emidr","171209000057"}, //左枪电表

  {"DEV","encryp", "1"}, //加密设置 0 不加密 1 关键信息加密 
  {"DEV","gunmode", "line"}, 
  {"DEV","showcost", "0"}, //结算显示电价 yes 1  no 0
  {"DEV","servstate", "1"}, //设备服务启停 1 开启 2 关闭充电服务,
  {"DEV","macset","0"},     //0 mac 使用自动分配，1 mac使用手动设置
  
  {"DEV", "gunnum","1"},  //充电枪个数
  {"DEV", "rip","47.96.7.231"}, //中心服务器地址  按照字节顺序
  {"DEV", "rport", "8188"},	//中心服务器端口 低字节在前
  {"DEV", "costshow", "0"},	//充电价格显示 1-禁止 0-启动，默认是 0
  {"DEV", "devid", "0755201911270019"}, //充电桩编码 32 ASCII 码
  {"DEV", "adminpwd", "123456"}, //管理员密码 8 ASCII 码
  {"DEV", "operpwd", "123456"}, //操作员密码（可选） 8 ASCII 码
  {"DEV", "mac", "08003e260a56"}, //MAC 地址 6 预留
  {"DEV", "qrcode", "http://ly.ewellcharge.com/app/device.html?dno="}, //左枪的二维码 128 ASCII 码 为充电枪的二维码 hlht://TEST0004901.101437000/    

};

static struct ini_file Ifile;

int32_t data_is_item_exist(const char_t *key){
    char_t buf[100]={0};
    return iniGetString(&Ifile, CONFIG_FILE_DEFAULT_PART, key, buf, sizeof(buf), NULL);
}

void data_check_item(void){
    int32_t i;
    for (i=0; i<sizeof(cfg_def)/sizeof(struct config_defult); i++){
        if(data_is_item_exist(cfg_def[i].key) == 0){
            log(LOG_INFO, "add config item %s=%s\r\n", cfg_def[i].key, cfg_def[i].value);
            iniSetString(&Ifile, CONFIG_FILE_DEFAULT_PART, cfg_def[i].key, cfg_def[i].value);
            
        }
    }
}

static void data_softver_set(void){
    char_t ver[100]={0};
    sprintf(ver, "%s %s %s", SOFT_VER, __DATE__, __TIME__);
    data_setstr("softver", ver);
    printf("ver:%s\r\n", ver); 
}

static void init_config(void){
    fs_fd fd;
	int32_t ret = fs_open(&fd, CONFIG_FILE, FS_O_RDWR | FS_O_CREAT);
	if (ret == 0){
		fs_truncate(&fd, 0);
        fs_sync(&fd);
		fs_close(&fd);
		iniFileLoad(&Ifile, CONFIG_FILE);
		int32_t i;
		for (i=0; i< sizeof(cfg_def)/sizeof(struct config_defult); i++){
			iniSetString(&Ifile, CONFIG_FILE_DEFAULT_PART, cfg_def[i].key, cfg_def[i].value);
		}
	}
}

int32_t config_init(void){
	if (fs_exist(CONFIG_FILE) == 0){ //不存在
		init_config();
	}else{
		//这里要先load后再check
		iniFileLoad(&Ifile, CONFIG_FILE);
        data_check_item();
	}
	
	//验证一些基本的参数
	int32_t gunnum = data_getint("gunnum");
	if (gunnum > SDEV_NUM_MAX){
		log(LOG_ERR, "gunnum:%d err\r\n", gunnum);
		return -1;
	}

    //生成版本号
    data_softver_set();
    
	return 0;
}

int32_t data_update_config(void){
    return iniFileLoad(&Ifile, CONFIG_FILE);
}

//周期性经常变动的参数放在这个文件中
static T_runTimeInfo g_runTimeInfo = {
    .powOnCnt = 0,  //启动次数
    .lastPowOn = {0},  //上一次启动时间
    .lastSignIn = {0}, //上一次签到时间 
    .lastCharge = {0},
};

void GtcData_RunTimeInfoPrint(T_runTimeInfo *info){
    printf("powOnCnt:%d\r\n", (int32_t)info->powOnCnt);
    
    printf("lastPowOn:%d-%d-%d %d:%d:%d\r\n", (int32_t)info->lastPowOn.year, (int32_t)info->lastPowOn.month, (int32_t)info->lastPowOn.date, 
                                                    (int32_t)info->lastPowOn.hour, (int32_t)info->lastPowOn.min, (int32_t)info->lastPowOn.sec);
    printf("lastSignIn:%d-%d-%d %d:%d:%d\r\n", (int32_t)info->lastSignIn.year, (int32_t)info->lastSignIn.month, (int32_t)info->lastSignIn.date, 
                                                    (int32_t)info->lastSignIn.hour, (int32_t)info->lastSignIn.min, (int32_t)info->lastSignIn.sec); 
}

static void GtcData_RunTimeInfoInit() {
    fs_fd fd;
    int32_t ret = 0;
    if (fs_exist(FLASH_RUNTIMEINFOFILE) == 0){
        printf("GtcData_RunTimeInfoInit file not exist\r\n");  
		ret = fs_open(&fd, FLASH_RUNTIMEINFOFILE, (uint32_t)FS_O_RDWR | (uint32_t)FS_O_CREAT);		
        if (ret == 0) {
            fs_lseek(&fd, 0, FS_SEEK_SET);
            fs_write(&fd, (char_t *)&g_runTimeInfo, sizeof(T_runTimeInfo));
            fs_sync(&fd);
            fs_close(&fd); 
        }        
    } else {
        printf("GtcData_RunTimeInfoInit file exist\r\n");
		ret = fs_open(&fd, FLASH_RUNTIMEINFOFILE, (uint32_t)FS_O_RDWR);
        if (ret == 0) {
            fs_lseek(&fd, 0, FS_SEEK_SET);
            fs_read(&fd, (char_t *)&g_runTimeInfo, sizeof(T_runTimeInfo));
            fs_close(&fd);
        }    
    }
    GtcData_RunTimeInfoPrint(&g_runTimeInfo);
}

void data_save_run_time_info(void){
    fs_fd fd;
    int32_t ret = 0;
	ret = fs_open(&fd, FLASH_RUNTIMEINFOFILE, (uint32_t)FS_O_RDWR | (uint32_t)FS_O_CREAT);		
    if (ret == 0) {
        fs_lseek(&fd, 0, FS_SEEK_SET);
        fs_write(&fd, (char_t *)&g_runTimeInfo, sizeof(T_runTimeInfo));
        fs_sync(&fd);
        fs_close(&fd);
    }
}

int32_t data_get_sys_power_on_cnt(void){
    return g_runTimeInfo.powOnCnt;
}

void data_set_sys_power_on_cnt(void){
    g_runTimeInfo.powOnCnt++;
    data_save_run_time_info();
}

int32_t data_get_last_power_on_time_value(char_t *value){
    T_TimeFmt *time = &g_runTimeInfo.lastPowOn;
    T_TimeFmt *val = (T_TimeFmt *)value;
    val->year = time->year;
    val->month = time->month;
    val->date = time->date;
    val->hour = time->hour;
    val->min = time->min;
    val->sec = time->sec;
    printf("*****************************last power on time: %4d%02d%02d%02d%02d%02d\r\n", time->year, time->month, time->date, time->hour,time->min,time->sec);
    return 0;
}

int32_t data_get_last_power_on_time_str(char_t *str){
    T_TimeFmt *time = &g_runTimeInfo.lastPowOn;
    sprintf(str, "%4d%02d%02d%02d%02d%02d", time->year, time->month, time->date, time->hour,time->min,time->sec);
    return 0;
}

void data_set_last_power_on_time(T_TimeFmt *time){
    memcpy(&g_runTimeInfo.lastPowOn, time, sizeof(g_runTimeInfo.lastPowOn));
    data_save_run_time_info();
}

int32_t data_get_last_charge_time_value(char_t *value){
    T_TimeFmt *time = &g_runTimeInfo.lastCharge;
    T_TimeFmt *val = (T_TimeFmt *)value;
    val->year = time->year;
    val->month = time->month;
    val->date = time->date;
    val->hour = time->hour;
    val->min = time->min;
    val->sec = time->sec;
    return 0;
}

int32_t data_get_last_charge_time_str(char_t *str){
    T_TimeFmt *time = &g_runTimeInfo.lastCharge;
    sprintf(str, "%4d%02d%02d%02d%02d%02d", time->year, time->month, time->date, time->hour,time->min,time->sec);
    return 0;
}

void data_set_last_charge_time(T_TimeFmt *time){
    memcpy(&g_runTimeInfo.lastCharge, time, sizeof(g_runTimeInfo.lastCharge));
    data_save_run_time_info();
}


int32_t data_getint(const char_t *key){
	return iniGetInt(&Ifile, CONFIG_FILE_DEFAULT_PART, key, 0);
}

float data_getfloat(const char_t *key){
	return iniGetDouble(&Ifile, CONFIG_FILE_DEFAULT_PART, key, 0);
}

int32_t data_getstr(const char_t *key, char_t *str, int32_t size){
	return iniGetString(&Ifile, CONFIG_FILE_DEFAULT_PART, key, str, size, NULL);
}

int32_t data_is_key_exist(const char_t *key){
    char_t buf[50]={0};
    return data_getstr(key, buf, sizeof(buf));
}

int32_t data_setint(const char_t *key, uint32_t value, int32_t mode){
	return iniSetInt(&Ifile, CONFIG_FILE_DEFAULT_PART, key, value, mode);
}

int32_t data_setfloat(const char_t *key, float value){
	char_t buf[20]={0};
	sprintf(buf, "%f", value);
	return iniSetString(&Ifile, CONFIG_FILE_DEFAULT_PART, key, buf);
}

int32_t data_setstr(const char_t *key, const char_t *str){
	return iniSetString(&Ifile, CONFIG_FILE_DEFAULT_PART, key, str);
}

int32_t GtcData_GetSubDevId(int32_t pos){
	return pos;
}

void GtcData_RunTimeInfoSaveToFile() {
    fs_fd fd;
    int32_t ret = 0;
	ret = fs_open(&fd, FLASH_RUNTIMEINFOFILE, (uint32_t)FS_O_RDWR | (uint32_t)FS_O_CREAT);
    if (ret == 0) {
        fs_lseek(&fd, 0, FS_SEEK_SET);
        fs_write(&fd, (char_t *)&g_runTimeInfo, sizeof(g_runTimeInfo));
        fs_sync(&fd);
        fs_close(&fd); 
    }
}

void GtcData_Sync(){

}


void GtcData_AddPowOnCnt(void){
    g_runTimeInfo.powOnCnt++;
    GtcData_RunTimeInfoSaveToFile();
}

uint32_t GtcData_GetPowOnCnt(void){
    return g_runTimeInfo.powOnCnt;
}

void GtcData_SetLastPowOn(T_TimeFmt *tim){
    memcpy(&g_runTimeInfo.lastPowOn, tim, sizeof(T_TimeFmt));
    GtcData_RunTimeInfoSaveToFile();
}

T_TimeFmt *GtcData_GetLastPowOn(void) {
    return &g_runTimeInfo.lastPowOn;
}

void GtcData_SetLastSignIn(T_TimeFmt *tim){
    memcpy(&g_runTimeInfo.lastSignIn, tim, sizeof(T_TimeFmt));
    GtcData_RunTimeInfoSaveToFile();
}

T_TimeFmt *GtcData_GetLastSignIn(void){
    return &g_runTimeInfo.lastSignIn;
}

uint8_t GtcData_CheckUpdateFile() {
    if (fs_exist(FLASH_UPDATE_INFO_FILE) == 0) { //如果文件不存在
        return false;
    }

    return true;
}

static void GtcData_AddRecord(char_t *name, struct T_transRecord *transRecord) {
    fs_fd fd;
    int32_t ret = 0;
    ret = fs_open(&fd, name, (uint32_t)FS_O_RDWR | (uint32_t)FS_O_CREAT);
	if (ret == 0)
	{    
		printf("GtcData_AddRecord:%s dno:%s\r\n", name, transRecord->dno);
		fs_lseek(&fd, 0, FS_SEEK_END);
		fs_write(&fd, (char_t *)transRecord, sizeof(struct T_transRecord));
        fs_sync(&fd);
		fs_close(&fd);
	}
}

void GtcData_UpdateRecord(char_t *name, struct T_transRecord *transRecord) {
    fs_fd fd;
    int32_t ret = 0;
    ret = fs_open(&fd, name, (uint32_t)FS_O_RDWR);
    if (ret != 0)	{
		//TODO log
		return;
	}
        
    printf("GtcData_UpdateRecord:%s dno:%s tkwh:%d tsec:%d\r\n", name, transRecord->dno, transRecord->acc_kwh, transRecord->acc_second);
    int32_t size  = (int32_t)(fs_size(&fd) / (int32_t)sizeof(struct T_transRecord));

    struct T_transRecord recordread = {0};
	int32_t i;
    for(i = 0; i < size; i++) {
        memset((uint8_t *)&recordread, 0, sizeof(struct T_transRecord));
        fs_lseek(&fd, i * (int32_t)sizeof(struct T_transRecord), FS_SEEK_SET);
        fs_read(&fd, (char_t *)&recordread, sizeof(struct T_transRecord));
        if(strcmp((char_t *)transRecord->dno, (char_t *)recordread.dno) == 0) {
            fs_lseek(&fd, i * (int32_t)sizeof(struct T_transRecord), FS_SEEK_SET);
            fs_write(&fd, (char_t *)transRecord, sizeof(struct T_transRecord));
            break;
        }
    }
    fs_sync(&fd);
    fs_close(&fd);
    
}

int32_t GtcData_ReadRecordDno(const char_t *name, const char_t *dno, struct T_transRecord *record) {
    fs_fd fd;
	int32_t ret = 0;
    ret = fs_open(&fd, name, (uint32_t)FS_O_RDWR);
    if (ret != 0){
        return ret;
    }
    
    struct T_transRecord recordread;
    int32_t size  = fs_size(&fd) / (int32_t)sizeof(struct T_transRecord);
	int32_t i;
    for(i = 0; i < size; i++) {
        memset((uint8_t *)&recordread, 0, sizeof(struct T_transRecord));
        fs_lseek(&fd, i * (int32_t)sizeof(struct T_transRecord), FS_SEEK_SET);
        fs_read(&fd, (char_t *)&recordread, sizeof(struct T_transRecord));
        if(strcmp((char_t *)dno, (char_t *)recordread.dno) == 0) {
            memcpy(record, &recordread, sizeof(struct T_transRecord));
            ret = 1;
			break;
        }
    }
    fs_close(&fd);
    return ret;
}

int32_t GtcData_ReadRecordBtime(const char_t *name, uint32_t btime, struct T_transRecord *record) {
    fs_fd fd;
	int32_t ret = 0;
    ret = fs_open(&fd, name, (uint32_t)FS_O_RDWR);
    if (ret != 0){
        return ret;
    }
    
    struct T_transRecord recordread;
    int32_t size  = fs_size(&fd) / (int32_t)sizeof(struct T_transRecord);
	int32_t i;
    for(i = 0; i < size; i++) {
        memset((uint8_t *)&recordread, 0, sizeof(struct T_transRecord));
        fs_lseek(&fd, i * (int32_t)sizeof(struct T_transRecord), FS_SEEK_SET);
        fs_read(&fd, (char_t *)&recordread, sizeof(struct T_transRecord));
        if(btime == recordread.beginTime) {
            memcpy(record, &recordread, sizeof(struct T_transRecord));
            ret = 1;
			break;
        }
    }
    fs_close(&fd);
    return ret;
}

int32_t GtcData_ReadRecordPos(const char_t *name, uint32_t pos, struct T_transRecord *record) {
    fs_fd fd;
	int32_t ret = 0;

    ret  = fs_open(&fd, name, (uint32_t)FS_O_RDWR);
	if (ret == 0){
		fs_lseek(&fd, (int32_t)(pos * (int32_t)sizeof(struct T_transRecord)), FS_SEEK_SET);
		fs_read(&fd, (char_t *)record, sizeof(struct T_transRecord));
		fs_close(&fd);		
		return 1;
	}
    return 0;
}
uint32_t GtcData_ReadRecordSize(const char_t *name, int32_t itemSize) {
    uint32_t size = 0;
	if(fs_exist(name) == 0) {
        return size;
    }
    fs_fd fd;
    int32_t ret = 0;
    ret = fs_open(&fd, name, (uint32_t)FS_O_RDWR);
	if (ret == 0){
		size = (uint32_t)(fs_size(&fd) / itemSize);
		fs_close(&fd);
	}

    return size;
}

void GtcData_PrintfRecord(const char_t *name) {
    fs_fd fd;
    int32_t ret = 0;
    ret = fs_open(&fd, name, (uint32_t)FS_O_RDWR);
	if (ret != 0){
		return;
	}

    struct T_transRecord recordread;

    int32_t size  = fs_size(&fd) / (int32_t)sizeof(struct T_transRecord);
    printf("size = %d\r\n", (int32_t)size);
	int32_t i;
    for(i = 0; i < size; i++) {
        memset((uint8_t *)&recordread, 0, sizeof(struct T_transRecord));
        fs_lseek(&fd, i * (int32_t)sizeof(struct T_transRecord), FS_SEEK_SET);
        fs_read(&fd, (char_t *)&recordread, sizeof(struct T_transRecord));

        printf("/*********************************************************************************/\r\n");
        printf("recordState = %d\r\n", recordread.recordState);
        printf("log_time = %d\r\n", (int32_t)recordread.log_time);
        printf("devId = %s\r\n", recordread.devId);
        printf("subId = %02x\r\n", recordread.subId);
        printf("btime = %d\r\n", (int32_t)recordread.beginTime);
        printf("etime = %d\r\n", (int32_t)recordread.endTime);
        printf("dno = %s\r\n", recordread.dno);
        printf("rno = %s\r\n", recordread.rno);
        printf("userId = %s\r\n", recordread.userId);
        printf("cardId = %s\r\n", recordread.cardId);
        printf("cType = %d\r\n", recordread.cType);
        printf("cTypeValue = %d\r\n", (int32_t)recordread.cTypeValue);
        printf("end_reason = %s\r\n", recordread.end_reason);
        printf("acc_ah = %d\r\n", recordread.acc_ah);
        printf("acc_kwh = %d\r\n", recordread.acc_kwh);
        printf("acc_second = %d\r\n", (int32_t)recordread.acc_second);
        printf("av_power = %d\r\n", (int32_t)recordread.av_power);
        printf("meter_start = %d\r\n", (int32_t)recordread.meter_start);
        printf("meter_end = %d\r\n", (int32_t)recordread.meter_end);

        printf("/*********************************************************************************/\r\n");
    }
    fs_close(&fd);
}

static void GtcData_DeleteRecord(char_t *name, const char_t *dno) {
    fs_fd fd;
    fs_fd fdtmp;
    int32_t ret = 0;
    uint32_t size = GtcData_ReadRecordSize(name, sizeof(struct T_transRecord));

    struct T_transRecord record;
	int32_t i,j;
    for(i = 0 , j = 0; i < size; i++) {
        memset((uint8_t *)&record, 0, sizeof(struct T_transRecord));

        ret = fs_open(&fd, name, (uint32_t)FS_O_RDWR);
		if (ret != 0){
			log(LOG_ERR, "open file %s err dno:%x\r\n", name, dno);
			return;
		}

        fs_lseek(&fd, (int32_t)i * (int32_t)sizeof(struct T_transRecord), FS_SEEK_SET);
        fs_read(&fd, (char_t *)&record, sizeof(struct T_transRecord));

        fs_close(&fd);

        if(strcmp((char_t *)dno, record.dno) == 0) {

        } else {
            ret = fs_open(&fdtmp, (char_t *)FLASH_RECORDTMP, (uint32_t)FS_O_CREAT | (uint32_t)FS_O_RDWR);
            if (ret != 0){
				log(LOG_ERR, "open file %s err dno:%x\r\n", FLASH_RECORDTMP, dno);
				return;
			}

            fs_lseek(&fdtmp, (int32_t)j * (int32_t)sizeof(struct T_transRecord), FS_SEEK_SET);
            fs_write(&fdtmp, (char_t *)&record, sizeof(struct T_transRecord));
            j++;

            fs_sync(&fdtmp);
            fs_close(&fdtmp);
        }
    }

    fs_delete(name);//删除文件
    if (fs_exist(FLASH_RECORDTMP)) {
        fs_rename(FLASH_RECORDTMP, name); //重命名
    }
}

void GtcData_Rm(const char_t *name) {
    if (fs_exist(name)) {
        fs_delete(name);
    }
}

//正在充电中记录
void GtcData_AddRecordCharging(struct T_transRecord *transRecord) {
    GtcData_AddRecord(FLASH_RECORDCHARGING, transRecord);
}
void GtcData_UpdateRecordCharging(struct T_transRecord *transRecord) {
    GtcData_UpdateRecord(FLASH_RECORDCHARGING, transRecord);
}
int32_t GtcData_ReadRecordChargingDno(const char_t *dno, struct T_transRecord *record) {
    return GtcData_ReadRecordDno(FLASH_RECORDCHARGING, dno, record);
}
int32_t GtcData_ReadRecordChargingPos(uint32_t pos, struct T_transRecord *record) {
    return GtcData_ReadRecordPos(FLASH_RECORDCHARGING, pos, record);
}
uint32_t GtcData_ReadRecordChargingSize() {
    return GtcData_ReadRecordSize(FLASH_RECORDCHARGING, sizeof(struct T_transRecord));
}
void GtcData_PrintfRecordCharging() {
    GtcData_PrintfRecord(FLASH_RECORDCHARGING);
}
void GtcData_DeleteRecordCharging(const char_t *dno) {
    GtcData_DeleteRecord(FLASH_RECORDCHARGING, dno);
}

//待上传记录
void GtcData_AddRecordWait(struct T_transRecord *transRecord) {
    GtcData_AddRecord(FLASH_RECORDWAITUPLOAD, transRecord);
}
void GtcData_UpdateRecordWait(struct T_transRecord *transRecord) {
    GtcData_UpdateRecord(FLASH_RECORDWAITUPLOAD, transRecord);
}
int32_t GtcData_ReadRecordWaitDno(const char_t *dno, struct T_transRecord *record) {
    return GtcData_ReadRecordDno(FLASH_RECORDWAITUPLOAD, dno, record);
}
int32_t GtcData_ReadRecordWaitPos(uint32_t pos, struct T_transRecord *record) {
    return GtcData_ReadRecordPos(FLASH_RECORDWAITUPLOAD, pos, record);
}
uint32_t GtcData_ReadRecordWaitSize() {
    return GtcData_ReadRecordSize(FLASH_RECORDWAITUPLOAD, sizeof(struct T_transRecord));
}
void GtcData_PrintfRecordWait() {
    GtcData_PrintfRecord(FLASH_RECORDWAITUPLOAD);
}
void GtcData_DeleteRecordWait(const char_t *dno) {
    GtcData_DeleteRecord(FLASH_RECORDWAITUPLOAD, dno);
}

//历史记录
void GtcData_AddRecordHistory(struct T_transRecord *transRecord) {
    GtcData_AddRecord(FLASH_RECORDHISTROYFILE, transRecord);
}
uint32_t GtcData_ReadRecordHistorySize() {
    return GtcData_ReadRecordSize(FLASH_RECORDHISTROYFILE, sizeof(struct T_transRecord));
}

void GtcData_TransRecordStateToWaitUp(char_t *dno) {
    printf("GtcData_TransRecordStateToWaitUp dno:%s\r\n", dno);
    struct T_transRecord record;
    if (GtcData_ReadRecordDno(FLASH_RECORDCHARGING, dno, &record)) {
        GtcData_AddRecord(FLASH_RECORDWAITUPLOAD, &record);
        GtcData_DeleteRecord(FLASH_RECORDCHARGING, dno);
    }
}

void GtcData_TransRecordStateToWaitUpAll() {
    uint32_t cnt = GtcData_ReadRecordChargingSize();
	int32_t i;
    for (i = 0; i< cnt; i++) {
        struct T_transRecord record = {0};
        GtcData_ReadRecordChargingPos(i, &record);
        strcpy(record.end_reason, "reboot");
        GtcData_AddRecordWait(&record);
    }
    
    GtcData_Rm(FLASH_RECORDCHARGING);
    
}

static void GtcData_AddHistoryRecord(struct T_transRecord *record) {

    //文件1还有空间，存入文件1
    int32_t file1size = (int32_t)GtcData_ReadRecordSize(FLASH_RECORDHISTROYFILE, sizeof(struct T_transRecord));
    if (file1size < FLASH_RECORD_HISTORY_MAX) {
        GtcData_AddRecord(FLASH_RECORDHISTROYFILE, record);
        file1size = (int32_t)GtcData_ReadRecordSize(FLASH_RECORDHISTROYFILE, sizeof(struct T_transRecord));
        if (file1size + 1 >= FLASH_RECORD_HISTORY_MAX) {
            GtcData_Rm(FLASH_RECORDHISTROYFILE2);
        }
    }
    //文件1没有空间，判断文件2
    else {
        //文件2还有空间，存入文件2
        int32_t file2size = (int32_t)GtcData_ReadRecordSize(FLASH_RECORDHISTROYFILE2, sizeof(struct T_transRecord));
        if (file2size < FLASH_RECORD_HISTORY_MAX) {
            GtcData_AddRecord(FLASH_RECORDHISTROYFILE2, record);
            file2size = (int32_t)GtcData_ReadRecordSize(FLASH_RECORDHISTROYFILE2, sizeof(struct T_transRecord));
            if (file2size + 1 >= FLASH_RECORD_HISTORY_MAX) {
                GtcData_Rm(FLASH_RECORDHISTROYFILE);
            }
        }else{
            GtcData_Rm(FLASH_RECORDHISTROYFILE);
            GtcData_AddRecord(FLASH_RECORDHISTROYFILE, record);
        }
    }
}

void GtcData_TransRecordStateToHistory(char_t *dno) {
    printf("GtcData_TransRecordStateToHistory dno:%s\r\n", dno);
    struct T_transRecord record;
    if (GtcData_ReadRecordDno(FLASH_RECORDWAITUPLOAD, dno, &record)) {
        GtcData_AddHistoryRecord(&record);
        GtcData_DeleteRecord(FLASH_RECORDWAITUPLOAD, dno);
    }
}

void GtcData_TransRecordStateToHistoryByBeginTime(char_t *time) {
    char_t timstr[30];
    RTC_GetTimeFmtStr((T_TimeFmt *)time, timstr);
    printf("GtcData_TransRecordStateToHistory btime: %s\r\n", timstr);
    
    uint32_t btime = RTC_GetTimeFmtSec((T_TimeFmt *)time);
    struct T_transRecord record;
    if (GtcData_ReadRecordBtime(FLASH_RECORDWAITUPLOAD, btime, &record)) {
        GtcData_AddHistoryRecord(&record);
        GtcData_DeleteRecord(FLASH_RECORDWAITUPLOAD, record.dno);
    }
}

void GtcData_SaveUpdateInfoFile(uint8_t *info, uint32_t len) {
    fs_fd fd;
    int32_t ret = 0;
	  ret = fs_open(&fd, FLASH_UPDATE_INFO_FILE, (uint32_t)FS_O_CREAT | (uint32_t)FS_O_RDWR);
    if (ret == 0) {
        fs_lseek(&fd, 0, FS_SEEK_SET);
        fs_write(&fd, (char_t *)info, len);
        fs_sync(&fd);
        fs_close(&fd);
    }
}

int32_t GtcData_GetUpdateInfo(uint8_t *info, uint32_t len) {
    fs_fd fd;
    int32_t ret = 0;

    if (fs_exist(FLASH_UPDATE_INFO_FILE) == 0) { //如果文件不存在
        return 0;
    }
	ret = fs_open(&fd, FLASH_UPDATE_INFO_FILE, (uint32_t)FS_O_RDWR);
    if (ret == 0) {
        fs_lseek(&fd, 0, FS_SEEK_SET);
        fs_read(&fd, (char_t *)info, len);
        fs_close(&fd);
        return 1;
    }

    return 0;
}

int32_t GtcData_PushUpdateFileData(const char_t *name, int32_t pos, char_t *buf, int32_t len) {
    fs_fd fd;
    int32_t ret = 0;
	ret = fs_open(&fd, name, (uint32_t)FS_O_CREAT | (uint32_t)FS_O_RDWR);
    if (ret == 0) {
        fs_lseek(&fd, pos, FS_SEEK_SET);
        fs_write(&fd, (char_t *)buf, (uint32_t)len);
        fs_sync(&fd);
        fs_close(&fd);
        return 0;
    }
    return -1;
}

static char_t g_shareMem[250] = {0};
void GtcData_SetShareMem(const char_t *buf, int32_t len) {
    if (len > (int32_t)sizeof(g_shareMem)) {
        printf("GtcData_SetShareMem len: %d err\r\n", len);
        return;
    }

    memcpy(g_shareMem, buf, (uint32_t)len);
}

void GtcData_GetShareMem(char_t *buf, int32_t len) {
    if (len > (int32_t)sizeof(g_shareMem)) {
        printf("GtcData_GetShareMem len: %d err\r\n", len);
        len = sizeof(g_shareMem);
    }

    memcpy(buf, g_shareMem, (uint32_t)len);
}

//计费规则
static struct T_CostInfo g_costInfo = {0};

void GtcData_SetCostSimple(const struct T_CostInfo *costInfo) {
    memcpy(&g_costInfo, costInfo, sizeof(g_costInfo));
    printf("cost elec:%d\r\n", (int32_t)g_costInfo.elecCost);
    printf("cost serv:%d\r\n", (int32_t)g_costInfo.servCost);
}

uint32_t GtcData_GetElecCost() {
    return g_costInfo.elecCost;
}

uint32_t GtcData_GetServCost() {
    return g_costInfo.servCost;
}

void GtcData_Ls() {
    //Lfs_Ls();
}

int32_t data_init() {
    fs_init();
	if (config_init() != 0){
		return -1;
	}
    GtcData_RunTimeInfoInit();
	return 0;
}

void data_show_config(void){
    printf("config data:\r\n%s", Ifile.buf);
}

uint32_t GtcData_ReadTraceSize(const char_t *name) {
    uint32_t size = 0;
	if(fs_exist(name) == 0) {
        return size;
    }
    fs_fd fd;
    int32_t ret = 0;
    ret = fs_open(&fd, name, (uint32_t)FS_O_RDONLY);
	if (ret == 0){
		size = (uint32_t)fs_size(&fd);
		fs_close(&fd);
	}

    return size;
}

static void GtcData_AddTraceInfo(char_t *name, char_t *msg) {
    fs_fd fd;
    int32_t ret = 0;
    ret = fs_open(&fd, name, (uint32_t)FS_O_RDWR | (uint32_t)FS_O_CREAT);
	if (ret == 0)
	{
		int32_t size  = fs_size(&fd);
		fs_lseek(&fd, size, FS_SEEK_SET);
		fs_write(&fd, (char_t *)msg, strlen(msg));
        fs_sync(&fd);
		fs_close(&fd);	
	}
}


void data_add_trace(char_t *msg) {

    //文件1还有空间，存入文件1
    int32_t file1size = (int32_t)GtcData_ReadTraceSize(FLASH_RECORD_TRACE);
    if (file1size < FLASH_RECORD_TRACE_MAX) {
        GtcData_AddTraceInfo(FLASH_RECORD_TRACE, msg);
        file1size = (int32_t)GtcData_ReadTraceSize(FLASH_RECORD_TRACE);
        if (file1size + 1 >= FLASH_RECORD_TRACE_MAX) {
            GtcData_Rm(FLASH_RECORD_TRACE2);
        }
    }
    //文件1没有空间，判断文件2
    else {
        //文件2还有空间，存入文件2
        int32_t file2size = (int32_t)GtcData_ReadTraceSize(FLASH_RECORD_TRACE2);
        if (file2size < FLASH_RECORD_TRACE_MAX) {
            GtcData_AddTraceInfo(FLASH_RECORD_TRACE2, msg);
            file2size = (int32_t)GtcData_ReadTraceSize(FLASH_RECORD_TRACE2);
            if (file2size + 1 >= FLASH_RECORD_TRACE_MAX) {
                GtcData_Rm(FLASH_RECORD_TRACE);
            }
        }else{
            GtcData_Rm(FLASH_RECORD_TRACE);
            GtcData_AddTraceInfo(FLASH_RECORD_TRACE, msg);
        }
    }
}


int32_t data_upgrade_config_file_set(char_t *url, char_t *md5){
    fs_fd fd;
    int32_t ret = 0;
    fs_delete(UPGRADE_CONFIG_FILE);
    ret = fs_open(&fd, UPGRADE_CONFIG_FILE, FS_O_RDWR | FS_O_CREAT);
    if (ret != 0){
        return -1;
    }
    char_t buf[300]={0};
    sprintf(buf, "url=%s\r\nmd5=%s\r\n", url, md5);
    fs_lseek(&fd, 0, FS_SEEK_SET);
    fs_write(&fd, buf, strlen(buf));
    fs_sync(&fd);
    fs_close(&fd);
    return 0;
}


static char_t *g_event_desc[]={
    "sysup", /*EVENT_SYSUP=0*/ 
    "netlink", /*EVENT_NETON*/ 
    "netunlink", /*EVENT_NETOFF*/  
    "gunon", /*EVENT_GUNIN*/   
    "gunoff", /*EVENT_GUNOFF*/  
    "start", /*EVENT_START_CHARGE*/  
    "stop", /*EVENT_END_CHARGE*/   
    "updatesucc"  /*EVENT_UPDATE_SUCCESS*/ 
};

int32_t event_add_info(char_t *name, int32_t gunid, int32_t type, int32_t code, const char_t *desc){
    static const char_t eventType[]={'E', 'A', 'R'};
    fs_fd fd;
    int32_t ret = 0;
    ret = fs_open(&fd, name, FS_O_RDWR|FS_O_CREAT);
    if (ret != 0){
        return -1;
    }
    
    char_t tim[16] = {0};
    rtc_get_currt_time_str(tim, sizeof(tim));
    char_t devnum[33]={0};
    data_getstr("devid", devnum, sizeof(devnum)-1);
    char_t buf[200]={0};
    //时间，桩号，枪号，类型，告警码，详细描述
    snprintf(buf, sizeof(buf), "%s,%s,%d,%c,%d,%s\r\n", tim,devnum,gunid,eventType[type],code,desc);
    int32_t size  = fs_size(&fd);
    fs_lseek(&fd, size, FS_SEEK_SET);
    fs_write(&fd, buf, strlen(buf));
    fs_sync(&fd);
    fs_close(&fd);  
    
    return 0;
}

void event_add(int32_t gunid, int32_t type, int32_t code, const char_t *desc) {

    //文件1还有空间，存入文件1
    int32_t file1size = (int32_t)GtcData_ReadTraceSize(FLASH_RECORD_EVENT);
    if (file1size < FLASH_RECORD_EVENT_MAX) {
        event_add_info(FLASH_RECORD_EVENT, gunid, type, code, desc);
        file1size = (int32_t)GtcData_ReadTraceSize(FLASH_RECORD_EVENT);
        if (file1size + 1 >= FLASH_RECORD_EVENT_MAX) {
            GtcData_Rm(FLASH_RECORD_EVENT2);
        }
    }
    //文件1没有空间，判断文件2
    else {
        //文件2还有空间，存入文件2
        int32_t file2size = (int32_t)GtcData_ReadTraceSize(FLASH_RECORD_EVENT2);
        if (file2size < FLASH_RECORD_EVENT_MAX) {
            event_add_info(FLASH_RECORD_EVENT2, gunid, type, code, desc);
            file2size = (int32_t)GtcData_ReadTraceSize(FLASH_RECORD_EVENT2);
            if (file2size + 1 >= FLASH_RECORD_EVENT_MAX) {
                GtcData_Rm(FLASH_RECORD_EVENT);
            }
        }else{
            GtcData_Rm(FLASH_RECORD_EVENT);
            event_add_info(FLASH_RECORD_EVENT, gunid, type, code, desc);
        }
    }
}

void alarm_log(int32_t gunid, int32_t type, int32_t code, const char_t *desc){
    event_add(gunid, type, code, desc);
}

void event_log(int32_t gunid, int32_t code){
    event_add(gunid, EVENT_EVENT, code, g_event_desc[code]);
}


int32_t data_save_update_info_file(char_t *info, uint32_t len) {
    fs_fd fd;
    if (fs_open(&fd, FLASH_UPDATE_INFO_FILE, (uint32_t)FS_O_CREAT | (uint32_t)FS_O_RDWR) == 0) {
        fs_lseek(&fd, 0, FS_SEEK_SET);
        fs_write(&fd, info, len);
        fs_close(&fd);
        return 0;
    }
    return -1;
}

int32_t dta_get_update_info(char_t *info, uint32_t len) {
    fs_fd fd;

    if (!fs_exist(FLASH_UPDATE_INFO_FILE)) { 
        return 0;
    }

    if (fs_open(&fd, FLASH_UPDATE_INFO_FILE,  FS_O_RDWR) == 0) {
        fs_lseek(&fd, 0, FS_SEEK_SET);

        fs_read(&fd, info, len);
        fs_close(&fd);
        return 1;
    }

    return 0;
}

int32_t data_push_update_file_data(const char *name, int32_t pos, char_t *buf, uint32_t len) {
    fs_fd fd;
    if (fs_open(&fd, name, FS_O_CREAT | FS_O_RDWR) != 0) {
        return -1;
    }
    
    fs_lseek(&fd, pos, FS_SEEK_SET);
    if (fs_write(&fd, buf, len) < 0){
        fs_close(&fd);
        return -1;
    }
    
    fs_close(&fd);
    return 0;
}


